package cn.fintecher.gis.service;

import cn.fintecher.gis.entity.*;
import cn.fintecher.gis.enums.Rapporttype;
import cn.fintecher.gis.model.MapSpotData;
import cn.fintecher.gis.model.request.LayerPublishRequest;
import cn.fintecher.gis.postgis.PostGISService;
import cn.fintecher.gis.respository.LayerInfoRepository;
import cn.fintecher.gis.respository.LayerPublishRepository;
import cn.fintecher.gis.respository.LayerStatisticalRepository;
import com.google.common.collect.Lists;
import com.querydsl.core.BooleanBuilder;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Service("layerStatisticalService")
public class LayerStatisticalService {

    private final Logger log = LoggerFactory.getLogger(LayerStatisticalService.class);

    @Autowired
    private LayerStatisticalRepository layerStatisticalRepository;

    @Autowired
    private LayerPublishRepository layerPublishRepository;

    @Autowired
    private LayerInfoRepository layerInfoRepository;

    @Autowired
    private PostGISService postGISService;

    @Autowired
    private LandQuoService landQuoService;

    @Autowired
    private LogInfoService logInfoService;

    final static Map<String, String> regulatoryMap = new HashMap<>();

    static {
        regulatoryMap.put("A1", "行政办公用地");
        regulatoryMap.put("A5", "医疗卫生用地");
        regulatoryMap.put("A6", "社会福利用地");
        regulatoryMap.put("A7", "文物古迹用地");
        regulatoryMap.put("A21", "图书馆展览用地");
        regulatoryMap.put("A22", "文化活动用地");
        regulatoryMap.put("A33", "中小学用地");
        regulatoryMap.put("A51", "医院用地");

        regulatoryMap.put("B11", "零售商业用地");
        regulatoryMap.put("B21", "金融保险用地");
        regulatoryMap.put("B41", "加油加气站用地");
        regulatoryMap.put("G1", "公园绿地");
        regulatoryMap.put("G2", "防护绿地");
        regulatoryMap.put("G3", "广场用地");
        regulatoryMap.put("M1", "一类工业用地");
        regulatoryMap.put("M2", "二类工业用地");
        regulatoryMap.put("R21", "住宅用地");
        regulatoryMap.put("R22", "服务设施用地");
        regulatoryMap.put("S41", "公共交通场站用地");
        regulatoryMap.put("S42", "社会停车场用地");
        regulatoryMap.put("U13", "供燃气用地");
        regulatoryMap.put("U15", "通信用地");
        regulatoryMap.put("U22", "环卫用地");
    }
    /**
     * 发布统计图层(土地利用现状一级分类)
     *
     * @param request
     */
    @Transactional
    public void addPublish(LayerPublishRequest request) throws Exception {
        LayerPublish layerPublish = new LayerPublish();
        BeanUtils.copyProperties(request, layerPublish);
        layerPublish = layerPublishRepository.save(layerPublish);
        List<MapSpotData> list = new ArrayList<>();
        for (String code : request.getLayerCode()) {
            List<MapSpotData> dataList = postGISService.queryMapSpot(null, code);
            list.addAll(dataList);
        }
        List<LayerStatistical> layerList = new ArrayList<>();
        getLayerStatisticalList(list, layerPublish.getReportType(), layerList);
        BigDecimal totalAcreage = new BigDecimal(0);
        Map<String,LayerStatistical> layerMap = new HashMap<>();//key为编号
        for (LayerStatistical statistical : layerList) {
            totalAcreage = totalAcreage.add(statistical.getAcreage());
            layerMap.put(statistical.getCode(),statistical);
        }
//        setLayerStatistical(layerList, totalAcreage, layerPublish);//处理图层名称的逻辑
        List<LayerStatistical> results = setLayerStatistical(layerMap,totalAcreage,layerPublish.getId(),layerPublish.getReportType());
        if (layerPublish.getReportType().equals(Rapporttype.LAND_CLASSIFICATION)) {//土地利用现状处理二级数据
            List<LayerStatistical> secondList = new ArrayList<>();
            setSecondClassification(list, secondList, layerPublish);
            results.addAll(secondList);
        }

        //处理图层中没有的代码编号
        layerStatisticalRepository.saveAll(results);
    }

    /**
     * 针对一级处理的方法
     * @param layerMap
     * @param reportType
     * @return
     */
    public List<LayerStatistical> setLayerStatistical(Map<String,LayerStatistical> layerMap,BigDecimal acreageTotal,
                                                      String publishId,Rapporttype reportType){
        List<LayerStatistical> results = new ArrayList<>();
        if (reportType.equals(Rapporttype.REGULATORY_PLAN)) { //控制性详细规划
            for(String key : regulatoryMap.keySet()){
                if(layerMap.containsKey(key)){
                    LayerStatistical layerStatistical = layerMap.get(key);
                    layerStatistical.setName(regulatoryMap.get(key));
                    layerStatistical.setAcreageTotal(acreageTotal);
                    layerStatistical.setPublishId(publishId);
                    BigDecimal ratio = layerStatistical.getAcreage().divide(acreageTotal, 4, RoundingMode.HALF_UP);
                    layerStatistical.setRatio(ratio);
                    results.add(layerStatistical);
                }else{
                    LayerStatistical layerStatistical = new LayerStatistical();
                    layerStatistical.setGrade(1);
                    layerStatistical.setAcreage(new BigDecimal(0));
                    layerStatistical.setAcreageTotal(acreageTotal);
                    layerStatistical.setRatio(new BigDecimal(0));
                    layerStatistical.setCode(key);
                    layerStatistical.setName(regulatoryMap.get(key));
                    layerStatistical.setPublishId(publishId);
                    results.add(layerStatistical);
                }
            }
        }else{
            List<LandQuo> landQuoList = landQuoService.getLandQuoByCode(reportType);
            for(LandQuo landQuo : landQuoList){
                if(layerMap.containsKey(landQuo.getCode())){ //查询出来存在的编号
                    LayerStatistical statistical = layerMap.get(landQuo.getCode());
                    statistical.setName(landQuo.getName());
                    statistical.setAcreageTotal(acreageTotal);
                    statistical.setPublishId(publishId);
                    BigDecimal ratio = statistical.getAcreage().divide(acreageTotal, 4, RoundingMode.HALF_UP);
                    statistical.setRatio(ratio);
                    results.add(statistical);
                }else{ //图层中不存在的编号，默认创建对象
                    LayerStatistical layerStatistical = new LayerStatistical();
                    layerStatistical.setName(landQuo.getName());
                    layerStatistical.setCode(landQuo.getCode());
                    layerStatistical.setRatio(new BigDecimal(0));
                    layerStatistical.setAcreageTotal(acreageTotal);
                    layerStatistical.setAcreage(new BigDecimal(0));
                    layerStatistical.setPublishId(publishId);
                    layerStatistical.setGrade(1);
                    results.add(layerStatistical);
                }
            }
        }
        return results;
    }


    /**
     * 土地利用现状处理二级数据
     *
     * @param list
     * @param secondList
     * @param layerPublish
     */
    public void setSecondClassification(List<MapSpotData> list, List<LayerStatistical> secondList, LayerPublish layerPublish) {
        List<LayerStatistical> third = new ArrayList<>();
        list.stream()
                .collect(Collectors.groupingBy(test -> (String) test.getAttr().get("DLBM"),
                        Collectors.summarizingDouble(test -> Double.valueOf(test.getAttr().get("XZDWMJ").toString()))))
                .forEach((String DLBM, DoubleSummaryStatistics sumTargetCost) -> {
                    LayerStatistical statistical = new LayerStatistical();
                    statistical.setCode(DLBM);
                    statistical.setAcreage(new BigDecimal(sumTargetCost.getSum()));
                    statistical.setGrade(2);
                    System.out.println(DLBM + "\t" + sumTargetCost.getSum());
                    third.add(statistical);
                });
        Map<String, BigDecimal> map = new HashMap<>();//分别求出各组的总面积
        Map<String,LayerStatistical> statisticalMap = new HashMap<>();
        for (LayerStatistical layerStatistical : third) {
            String code = StringUtils.substring(layerStatistical.getCode(), 0, layerStatistical.getCode().length() - 1);
            statisticalMap.put(layerStatistical.getCode(),layerStatistical);
            if (map.containsKey(code)) {
                BigDecimal area = layerStatistical.getAcreage().add(map.get(code));
                map.put(code, area);
            } else {
                map.put(code, layerStatistical.getAcreage());
            }
        }

        //分组设置比例和总面积
        List<LandQuo> firstLandQue = landQuoService.getLandQuoByCode(Rapporttype.LAND_CLASSIFICATION);
        for(LandQuo landQuo : firstLandQue){
            List<LandQuo> second = landQuoService.getSecondeLandQuo(landQuo.getId());
            for(LandQuo quo : second){
                if(statisticalMap.containsKey(quo.getCode())){
                    LayerStatistical layerStatistical = statisticalMap.get(quo.getCode());
                    layerStatistical.setCode(quo.getCode());
                    layerStatistical.setName(quo.getName());
//                    System.out.println("-----------------"+landQuo.getCode());
                    BigDecimal rabio = layerStatistical.getAcreage().divide(map.get(landQuo.getCode()),4, RoundingMode.HALF_UP);
                    layerStatistical.setAcreageTotal(map.get(landQuo.getCode()));
                    layerStatistical.setRatio(rabio);
                    layerStatistical.setPublishId(layerPublish.getId());
                    layerStatistical.setGrade(2);
                    secondList.add(layerStatistical);
                }else{
                    LayerStatistical layerStatistical = new LayerStatistical();
                    layerStatistical.setAcreage(new BigDecimal(0));
                    layerStatistical.setCode(quo.getCode());
                    layerStatistical.setName(quo.getName());
                    layerStatistical.setRatio(new BigDecimal(0));
                    layerStatistical.setPublishId(layerPublish.getId());
                    if(map.containsKey(landQuo.getCode())){
                        layerStatistical.setAcreageTotal(map.get(landQuo.getCode()));
                    }else{
                        layerStatistical.setAcreageTotal(new BigDecimal(0));
                    }
                    layerStatistical.setGrade(2);
                    secondList.add(layerStatistical);
                }
            }
        }
    }


    /**
     * 设置统计其他属性
     *
     * @param layerList
     * @param totalAcreage
     * @param layerPublish
     */
    public void setLayerStatistical(List<LayerStatistical> layerList, BigDecimal totalAcreage,
                                    LayerPublish layerPublish) {
        for (LayerStatistical layerStatistical : layerList) {
            layerStatistical.setAcreageTotal(totalAcreage);
            if (layerPublish.getReportType().equals(Rapporttype.REGULATORY_PLAN)) { //控制性详细规划
                if (regulatoryMap.containsKey(layerStatistical.getCode())) {
                    layerStatistical.setName(regulatoryMap.get(layerStatistical.getCode()));
                } else {
                    layerStatistical.setName("未知");
                }
            } else {
                List<LandQuo> landQuoList = landQuoService.getLandQuoByCode(layerStatistical.getCode(), layerPublish.getReportType());
                if (landQuoList != null && !landQuoList.isEmpty()) {
                    layerStatistical.setName(landQuoList.get(0).getName());
                }
            }
            BigDecimal ratio = new BigDecimal(0);
            if (totalAcreage.compareTo(BigDecimal.ZERO) == 0) {
                layerStatistical.setRatio(new BigDecimal(0));
            } else {
                ratio = layerStatistical.getAcreage().divide(totalAcreage, 4, RoundingMode.HALF_UP);
                layerStatistical.setRatio(ratio);
            }
            layerStatistical.setPublishId(layerPublish.getId());
        }
    }

    /**
     * 对图层数据进行整合
     *
     * @param dataList
     * @param reportType
     * @param layerStatisticals
     * @return
     */
    public List<LayerStatistical> getLayerStatisticalList(List<MapSpotData> dataList, Rapporttype reportType,
                                                          List<LayerStatistical> layerStatisticals) {
        if (reportType.equals(Rapporttype.LAND_CLASSIFICATION)) {  //土地利用现状一级分类统计
            dataList.stream()
                    .collect(Collectors.groupingBy(test -> StringUtils.substring((String) test.getAttr().get("DLBM"), 0, ((String) test.getAttr().get("DLBM")).length() - 1),
                            Collectors.summarizingDouble(test -> Double.valueOf(test.getAttr().get("XZDWMJ").toString()))))
                    .forEach((String DLBM, DoubleSummaryStatistics sumTargetCost) -> {
                        BigDecimal acreage = new BigDecimal(sumTargetCost.getSum());
                        System.out.println(DLBM + "\t" + sumTargetCost.getSum());
                        layerStatisticals.add(setLayerStatistical(DLBM,1,acreage));
                    });
        } else if (reportType.equals(Rapporttype.LAND_USE_AREA)) {//土地用途区统计
            dataList.stream()
                    .collect(Collectors.groupingBy(test -> (String) test.getAttr().get("TDYTQLXDM"),
                            Collectors.summarizingDouble(test -> Double.valueOf(test.getAttr().get("TDYTQMJ").toString()))))
                    .forEach((String DLBM, DoubleSummaryStatistics sumTargetCost) -> {
                        BigDecimal acreage = new BigDecimal(sumTargetCost.getSum());
                        //图层数据单位默认公顷，需要转换为平方米(这个需求确认过的)
                        acreage = acreage.multiply(new BigDecimal(10000));
                        System.out.println(DLBM + "\t" + sumTargetCost.getSum());
                        layerStatisticals.add(setLayerStatistical(DLBM,1,acreage));
                    });
        } else if (reportType.equals(Rapporttype.LAND_CONSTRUCTION)) { //建设用地管制区
            dataList.stream()
                    .collect(Collectors.groupingBy(test -> (String) test.getAttr().get("GZQLXDM"),
                            Collectors.summarizingDouble(test -> Double.valueOf(test.getAttr().get("GZQMJ").toString()))))
                    .forEach((String GZQLXDM, DoubleSummaryStatistics sumTargetCost) -> {
                        BigDecimal acreage = new BigDecimal(sumTargetCost.getSum());
                        //图层数据单位默认公顷，需要转换为平方米(这个需求确认过的)
                        acreage = acreage.multiply(new BigDecimal(10000));
                        System.out.println(GZQLXDM + "\t" + sumTargetCost.getSum());
                        layerStatisticals.add(setLayerStatistical(GZQLXDM,1,acreage));
                    });
        } else { //控制性详细规划()
            dataList.stream()
                    .collect(Collectors.groupingBy(test -> (String) test.getAttr().get("用地代码"),
                            Collectors.summarizingDouble(test -> Double.valueOf(test.getAttr().get("用地面积").toString()))))
                    .forEach((String DLBM, DoubleSummaryStatistics sumTargetCost) -> {
                        BigDecimal acreage = new BigDecimal(sumTargetCost.getSum());
                        System.out.println(DLBM + "\t" + sumTargetCost.getSum());
                        layerStatisticals.add(setLayerStatistical(DLBM,1,acreage));
                    });
        }
        return layerStatisticals;
    }

    public LayerStatistical setLayerStatistical(String code,Integer grade,BigDecimal acreage){
        LayerStatistical statistical = new LayerStatistical();
        statistical.setCode(code);
        statistical.setAcreage(acreage);
        statistical.setGrade(grade);
        return statistical;
    }


    /**
     * 对发布的统计数据图层进行查询
     *
     * @return
     */
    public List<LayerPublish> getLayerPublishList() {
        return layerPublishRepository.findAll();
    }

    /**
     * 对数据进行删除
     */
    @Transactional
    public void deleteLayerPublishById(String id) {
        Iterator<LayerStatistical> iterator = layerStatisticalRepository.findAll(QLayerStatistical.layerStatistical.publishId.eq(id)).iterator();
        layerStatisticalRepository.deleteAll(Lists.newArrayList(iterator));
        Optional<LayerPublish> optional = layerPublishRepository.findById(id);
        if (optional.isPresent()) {
            LayerPublish layerPublish = optional.get();
            logInfoService.addLog("LayerStatisticalController", "deleteLayerPublish",
                    "id=" + id, "删除了年份为：" + layerPublish.getYear() + "类型是:" + layerPublish.getReportType().toString() + "的报表数据");
            layerPublishRepository.delete(layerPublish);
        }
    }

    /**
     * 查询除了土地利用现状一级分类统计的其他三种类型
     * @param reportType
     * @return
     */
    public List<LayerStatistical> getLayerStatisticalReport(Rapporttype reportType) {
        List<LayerStatistical> list = new ArrayList<>();
        if (!reportType.equals(Rapporttype.LAND_CLASSIFICATION)) {
            Iterator<LayerPublish> iterator = layerPublishRepository.findAll(QLayerPublish.layerPublish.reportType.eq(reportType)).iterator();
            while (iterator.hasNext()) {
                LayerPublish layerPublish = iterator.next();
                Iterator<LayerStatistical> statisticalIterator = layerStatisticalRepository.findAll(QLayerStatistical.layerStatistical.publishId.eq(layerPublish.getId())).iterator();
                list.addAll(Lists.newArrayList(statisticalIterator));
            }
        }
        return list;
    }

    /**
     * 查询土地利用现状一级分类统计
     *
     * @param year
     * @return
     */
    public List<LayerStatistical> getClassificationOne(String year) {
        List<LayerStatistical> list = new ArrayList<>();
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        QLayerPublish qLayerPublish = QLayerPublish.layerPublish;
        booleanBuilder.and(qLayerPublish.reportType.eq(Rapporttype.LAND_CLASSIFICATION));
        booleanBuilder.and(qLayerPublish.year.eq(year));
        Iterator<LayerPublish> iterator = layerPublishRepository.findAll(booleanBuilder).iterator();
        while (iterator.hasNext()) {
            LayerPublish layerPublish = iterator.next();
            BooleanBuilder builder = new BooleanBuilder();
            QLayerStatistical qLayerStatistical = QLayerStatistical.layerStatistical;
            builder.and(qLayerStatistical.publishId.eq(layerPublish.getId()));
            builder.and(qLayerStatistical.grade.eq(1));
            Iterator<LayerStatistical> statisticalIterator = layerStatisticalRepository.findAll(builder).iterator();
            list = Lists.newArrayList(statisticalIterator);
        }
        return list;
    }

    /**
     * 查询土地利用现状二级分类统计
     *
     * @param publishId
     * @param code
     * @return
     */
    public List<LayerStatistical> getSecondClassification(String publishId, String code) {
        List<LayerStatistical> list = new ArrayList<>();
        BooleanBuilder builder = new BooleanBuilder();
        QLayerStatistical qLayerStatistical = QLayerStatistical.layerStatistical;
        builder.and(qLayerStatistical.publishId.eq(publishId));
        builder.and(qLayerStatistical.grade.eq(2));
        Iterator<LayerStatistical> iterator = layerStatisticalRepository.findAll(builder).iterator();
        while (iterator.hasNext()) {
            LayerStatistical layerStatistical = iterator.next();
            String secondCode = StringUtils.substring(layerStatistical.getCode(), 0, layerStatistical.getCode().length() - 1);
            if (secondCode.equals(code)) {
                list.add(layerStatistical);
            }
        }
        return list;
    }
}